/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core.resource;

import java.io.Serializable;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.text.StrBuilder;

/**
 * The ResourceData contain information obtained bay WURFLResource. At this
 * moment the managed ModelDevices, the name and version of resource.
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: ResourceData.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public class ResourceData implements Serializable, Comparable {

	/** Serial */
	private static final long serialVersionUID = 1L;

	/** Name of the resource */
	private String name;

	/** Version or the resource */
	private String version;

	/** Specifies if this resource is a patch */
	private boolean patch;

	/** Managed ModelDevices */
	private ModelDevices devices;

	/** Cached resource info */
	private transient String info;

	/**
	 * Build ResourceData by name, version and ModelDevices. By default this
	 * ResourceData is a root resource nor patch.
	 * 
	 * @param name
	 *            The name of source resource.
	 * @param version
	 *            The version of source Resource
	 * @param devices
	 *            The managed ModelDevices
	 */
	public ResourceData(String name, String version,
			ModelDevices devices) {
		this(name, version, false, devices);
	}

	/**
	 * Build ResourceData by name, version, patch flag and ModelDevices
	 * 
	 * @param name
	 *            The name of source resource.
	 * @param version
	 *            The version of source Resource
	 * @param patch
	 *            flag indicates if this resource is a patch.
	 * @param devices
	 *            The managed ModelDevices
	 */
	public ResourceData(String name, String version, boolean patch,
			ModelDevices devices) {
		super();
		this.name = name;
		this.version = version;
		this.patch = patch;
		this.devices = devices;
	}

	/**
	 * Returns the name of resource.
	 * 
	 * @return String represents the name of resource.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Returns version string of the resource.
	 * 
	 * @return String represents the version of resource.
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * Returns if this resource is a patch.
	 * 
	 * @return True if this resource is a patch, fase otherwise.
	 */
	public boolean isPatch() {
		return patch;
	}

	/**
	 * Return info string of this resource. Info string is in the format:
	 * <code>Root|Patch:Loacation:Version</code>. The location may vary from URI
	 * to JDBC connection string, it depends by the source Resource.
	 * 
	 * @return Info string for this resource.
	 */
	public String getInfo() {
		if (info == null) {
			StrBuilder infoBuilder = new StrBuilder();
			infoBuilder.append(patch ? "Patch" : "Root").append(":").append(
					name);
			if(StringUtils.isNotBlank(version)){
				infoBuilder.append(":").append(version);
			}
			info = infoBuilder.toString();
		}

		return info;
	}

	/**
	 * Returns maanged ModelDevices.
	 * 
	 * @return Set<ModelDevice> containing managed devices.
	 */
	public ModelDevices getDevices() {
		// defensive copy
		return new ModelDevices(devices);
	}

	// Comparable methods *************************************************

	public int compareTo(Object o) {
		ResourceData other = (ResourceData) o;
		CompareToBuilder cb = new CompareToBuilder();

		cb.append(name, other.name).append(version, other.version);

		return cb.toComparison();
	}

	// Commons methods ****************************************************

	public int hashCode() {
		HashCodeBuilder hb = new HashCodeBuilder(33, 55);

		hb.append(name).append(version);

		return hb.toHashCode();
	}

	/**
	 * ResourceData is equals to another, if and only if, the info string are
	 * equal.
	 * 
	 * {@inheritDoc}
	 * 
	 */
	public boolean equals(Object obj) {
		EqualsBuilder eb = new EqualsBuilder();

		eb.appendSuper(getClass().isInstance(obj));
		if (eb.isEquals()) {
			ResourceData other = (ResourceData) obj;
			eb.append(getInfo(), other.getInfo());
		}

		return eb.isEquals();
	}

	public String toString() {
		ToStringBuilder tb = new ToStringBuilder(this);

		tb.append(name).append(version);

		return tb.toString();
	}

}
